package com.touni.algorithm;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.*;

/**
 * @ClassName : HwDemo
 * @Description :
 * @Author : lwq
 * @Date: 2021-03-23 08:36
 */
public class HwDemo {

    public static void main(String[] args) {
        //juziNixu();
        //Object calculate = calculate("3+2*1+2*[-4/(8-6)+7]");
        //System.out.println(calculate.toString());
        SizeCal();
    }

    //[‘0’-‘9’],‘+’,‘-’, ‘*’,‘/’ ,‘(’， ‘)’,‘[’, ‘]’,‘{’ ,‘}’
    //用两个栈分别压数字和运算符；
    //如果当前运算符优先级('*/')高于栈顶运算符('+-')优先级，则将运算符入栈；
    // 反之，从数字栈中弹出两个数，从运算符栈中弹出栈顶运算符，进行运算，数字栈压入运算结果，符号栈压入当前运算符。重复该操作直到不满足条件。
    //出现左括号，则直接压入；出现右括号，则从数字栈中弹出两个数，
    // 从运算符栈中弹出栈顶运算符，进行运算，数字栈压入运算结果，重复该操作直到栈顶弹出右括号位置。
    public static void SizeCal() {
        String str111 = "3+2*{1+2*[2+9+7]}"; // 41
        Scanner scanner = new Scanner(System.in);
        char[] input = str111.toCharArray();
        Stack<Integer> numStack = new Stack<>();
        Stack<Character> fuhaoStack = new Stack<>();
        for (int i = 0; i < input.length; i++) {
            char cha = input[i];
            //是数字
            if ('0' <= cha && cha <= '9') {
                //考虑到两位数的 如下一位依然是数字 则需要把下一位

                numStack.push(Integer.valueOf(Character.toString(cha)));
            } else {
                //是符号
                if (!fuhaoStack.empty()) {
                    //符号 栈不为空
                    Character fuhaoStackLast = fuhaoStack.lastElement();
                    if (((cha == '/' || cha == '*') && (fuhaoStackLast == '+' || fuhaoStackLast == '-'))
                            || cha == '(' || cha == '[' || cha == '{' || fuhaoStackLast == '(' || fuhaoStackLast == '['
                            || fuhaoStackLast == '{') {
                        //如果当前运算符 大于 栈顶运算符  则入栈  如果当前运算符为左括号 则入栈
                        fuhaoStack.push(cha);
                    } else if (cha == ')' || cha == ']' || cha == '}') {
                        //闭合符号  进行运算
                        Character lastFuhao = fuhaoStack.pop();
                        Integer second = numStack.pop();
                        while ((cha == ')' && lastFuhao != '(') || (cha == '[' && lastFuhao != ']')
                                || (cha == '{' && lastFuhao != '}')) {
                            Integer first = numStack.pop();
                            Integer calResult = calll(first, second, lastFuhao);
                            lastFuhao = fuhaoStack.pop();
                            second = calResult;
                        }
                        numStack.push(second);
                    } else {
                        //如果当前运算符  小于等于栈顶运算符  则弹出两个数字 和一个计算符  用 倒数第二数 运算符 倒数第一数
                        Integer second = numStack.pop();
                        Integer first = numStack.pop();
                        Character lastFuhao = fuhaoStack.pop();
                        Integer calResult = calll(first, second, lastFuhao);
                        //将结果入栈
                        numStack.push(calResult);
                        fuhaoStack.push(cha);
                    }
                } else {
                    fuhaoStack.push(cha);
                }
            }
        }
        Character lastFuhao = fuhaoStack.pop();
        Integer second = numStack.pop();
        while (numStack.isEmpty()) {
            Integer first = numStack.pop();
            Integer calResult = calll(first, second, lastFuhao);
            lastFuhao = fuhaoStack.pop();
            second = calResult;
        }
        System.out.println(second);
    }

    public static Integer calll(Integer a,Integer b, char c){
        switch (c){
            case '+':
                return a+b;
            case '-':
                return a-b;
            case '*':
                return a*b;
            case '/':
                return a/b;
        }
        return null;
    }



    public static Object calculate(String s) {
        Object object = null;
        ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
        ScriptEngine nashorn = scriptEngineManager.getEngineByName("nashorn");

        try {
            object = nashorn.eval(s);
        } catch (ScriptException e) {
            object = "请输入正确表达式！！！ please input the correct formula!!!";
        }
        return object;
    }


    public static void zuoBiaoCal(){
        Scanner scanner = new Scanner(System.in);
        String inputStr = scanner.nextLine();
        String[] strings = inputStr.split(";");
        int i = 0;
        int j = 0;
        for (int k = 0; k < strings.length; k++) {
            char[] chars = strings[k].toCharArray();
            if (chars.length > 3 || chars.length < 2){
                break;
            }
            switch (chars[0]){
                case 'A':
                    StringBuilder stringBuilder = new StringBuilder();
                    if ('9' <= chars[1] || chars[1] >='0'){
                        stringBuilder.append(chars[1]);
                    }
                    break;
                case 'D':
                    break;
                case 'W':
                    break;
                case 'S':
                    break;
                default:
                    break;
            }

        }




    }



    //开发一个坐标计算工具， A表示向左移动，D表示向右移动，W表示向上移动，S表示向下移动。
    // 从（0,0）点开始移动，从输入字符串里面读取一些坐标，并将最终输入结果输出到输出文件里面。
    //
    //输入：
    //
    //合法坐标为A(或者D或者W或者S) + 数字（两位以内）
    //
    //坐标之间以;分隔。
    //
    //非法坐标点需要进行丢弃。如AA10;  A1A;  $%$;  YAD; 等。
    //
    //下面是一个简单的例子 如：
    //
    //A10;S20;W10;D30;X;A1A;B10A11;;A10;
    //
    //处理过程：    左： 左减    下  右减  上右加   右 左加
    //
    //起点（0,0）
    //
    //+   A10   =  （-10,0）
    //
    //+   S20   =  (-10,-20)
    //
    //+   W10  =  (-10,-10)
    //
    //+   D30  =  (20,-10)
    //
    //+   x    =  无效
    //
    //+   A1A   =  无效
    //
    //+   B10A11   =  无效
    //
    //+  一个空 不影响
    //
    //+   A10  =  (10,-10)
    //
    //结果 （10， -10）



    public static void shopping(){
        Scanner scanner = new Scanner(System.in);
        String[] totalInput = scanner.nextLine().split(" ");
        int n = Integer.valueOf(totalInput[0]); //金额
        int m = Integer.valueOf(totalInput[1]); // 购物数量
        List<Good> goodList = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            String[] strings = scanner.nextLine().split(" ");
            Good good = new Good(Integer.valueOf(strings[0]),Integer.valueOf(strings[1]),Integer.valueOf(strings[2]));
            goodList.add(good);
        }


    }

    private static class Good{
        public int v; //价格
        public int p; //重要度
        public int q; //0位附件

        public Good(int v,int p,int q){
            this.p = p;
            this.v = v;
            this.q = q;
        }

    }


    // 题目描述
    //王强今天很开心，公司发给N元的年终奖。王强决定把年终奖用于购物，他把想买的物品分为两类：主件与附件，附件是从属于某个主件的，下表就是一些主件与附件的例子：
    //主件	附件
    //电脑	打印机，扫描仪
    //书柜	图书
    //书桌	台灯，文具
    //工作椅	无
    //如果要买归类为附件的物品，必须先买该附件所属的主件。每个主件可以有 0 个、 1 个或 2 个附件。
    // 附件不再有从属于自己的附件。王强想买的东西很多，为了不超出预算，他把每件物品规定了一个重要度，
    // 分为 5 等：用整数 1 ~ 5 表示，第 5 等最重要。他还从因特网上查到了每件物品的价格（都是 10 元的整数倍）。
    // 他希望在不超过 N 元（可以等于 N 元）的前提下，使每件物品的价格与重要度的乘积的总和最大。
    //    设第 j 件物品的价格为 v[j] ，重要度为 w[j] ，共选中了 k 件物品，编号依次为 j 1 ， j 2 ，……， j k ，则所求的总和为：
    //v[j 1 ]*w[j 1 ]+v[j 2 ]*w[j 2 ]+ … +v[j k ]*w[j k ] 。（其中 * 为乘号）
    //    请你帮助王强设计一个满足要求的购物单。
    //
    //
    //
    //
    //输入描述:
    //输入的第 1 行，为两个正整数，用一个空格隔开：N m
    //
    //（其中 N （ <32000 ）表示总钱数， m （ <60 ）为希望购买物品的个数。）
    //
    //
    //从第 2 行到第 m+1 行，第 j 行给出了编号为 j-1 的物品的基本数据，每行有 3 个非负整数 v p q
    //
    //
    //（其中 v 表示该物品的价格（ v<10000 ）， p 表示该物品的重要度（ 1 ~ 5 ）， q 表示该物品是主件还是附件。如果 q=0 ，表示该物品为主件，如果 q>0 ，表示该物品为附件， q 是所属主件的编号）
    //
    //
    //
    //
    //输出描述:
    // 输出文件只有一个正整数，为不超过总钱数的物品的价格与重要度乘积的总和的最大值（ <200000 ）。
    //示例1
    //输入
    //复制
    //1000 5
    //800 2 0
    //400 5 1
    //300 5 1
    //400 3 0
    //500 2 0
    //输出
    //复制
    //2200













    public static void int2erNums(){
        Scanner scanner = new Scanner(System.in);
        int input = scanner.nextInt();
        char[] chars = Integer.toBinaryString(input).toCharArray();
        int count = 0;
        for (int i = 0; i < chars.length; i++) {
            if ('1' == chars[i]){
                count ++;
            }
        }
        System.out.println(count);
    }


    public static void strPaixu(){
        Scanner scanner = new Scanner(System.in);
        long total = scanner.nextInt();
        int i = 1;
        List<String> list = new ArrayList<>();
        while (i <= total){
            list.add(scanner.next());
            i++;
        }
        Collections.sort(list);
        list.forEach(str -> System.out.println(str));
    }



    //将一个英文语句以单词为单位逆序排放。例如“I am a boy”，逆序排放后为“boy a am I”
    //所有单词之间用一个空格隔开，语句中除了英文字母外，不再包含其他字符
    public static void juziNixu(){
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        String[] strings = input.split(" ");
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = strings.length -1 ; i >= 0 ; i--) {
            stringBuilder.append(strings[i]);
            if (i != 0){
                stringBuilder.append(" ");
            }
        }
    }




    public static void int2Str(){
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        char[] chars = input.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = chars.length -1; i >= 0; i--) {
            stringBuilder.append(chars[i]);
        }
        System.out.println(stringBuilder.toString());
    }


    public static void countCharNums(){
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        char[] chars = input.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] < 0 && chars[i] > 127){
                break;
            }
            int lastIndexOf = stringBuilder.lastIndexOf(String.valueOf(chars[i]));
            if (lastIndexOf == -1){
                stringBuilder.append(chars[i]);
            }
        }
        System.out.println(stringBuilder.length());
    }


    public static void getOnlyOneNum(){
        Scanner scanner = new Scanner(System.in);
        Integer nextInt = scanner.nextInt();
        char[] chars = nextInt.toString().toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = chars.length -1; i >= 0; i--){
            if (stringBuilder.lastIndexOf(String.valueOf(chars[i])) == -1){
                stringBuilder.append(chars[i]);
            }
        }
        System.out.println(stringBuilder.toString());
    }


    public static void mingmingRandom(){
        TreeSet<Integer> treeSet = new TreeSet<>();
        Scanner sc = new Scanner(System.in);
        int i = 0;
        while(sc.hasNext()){
            int input = sc.nextInt();
            if(i != 0){
                boolean isAdd = treeSet.add(input);
                if (!isAdd){
                    i = i-1;
                }
            } else {
                i = input;
            }
            if(i == treeSet.size()){
                i = 0;
                treeSet.forEach(integer -> System.out.println(integer));
                treeSet.clear();
            }
        }
    }


    //数据表记录包含表索引和数值（int范围的正整数），请对表索引相同的记录进行合并，
    // 即将相同索引的数值进行求和运算，输出按照key值升序进行输出。
    public static void hebingTable(){
        Scanner scanner = new Scanner(System.in);
        int totalSize = Integer.valueOf(scanner.nextLine());
        TreeMap<Integer,Integer> treeMap = new TreeMap<>();
        for (int i = 0; i < totalSize; i++) {
            String next = scanner.nextLine();
            String[] strings = next.split(" ");
            Integer value = treeMap.get(Integer.valueOf(strings[0]));
            if (value != null){
                value = value + Integer.valueOf(strings[1]);
                treeMap.put(Integer.valueOf(strings[0]),value);
            } else {
                treeMap.put(Integer.valueOf(strings[0]),Integer.valueOf(strings[1]));
            }
        }
        treeMap.forEach((key,value) -> System.out.println(key + " " + value));
    }




    public static void getZhengShu(){
        Scanner scanner = new Scanner(System.in);
        String next = scanner.next();
        if (next.contains(".")){
            String split = next.split("\\.")[1];
            if (split.length() > 1){
                split = split.substring(0,1);
            }
            if (Integer.valueOf(split) >= 5 ){
                System.out.println(Double.valueOf(next).intValue() + 1);
                return;
            }
        }
        System.out.println(Double.valueOf(next).intValue());
    }

    public static void fenJieZhiYinShu(){
        Scanner scanner = new Scanner(System.in);
        long nextLong = scanner.nextLong();
        int max = (int) Math.sqrt(nextLong);
        for (int i = 2; i <= max; i++) {
            while (i != nextLong){
                if (nextLong % i == 0){
                    System.out.print(i + " ");
                    nextLong = nextLong/i;
                } else {
                    break;
                }
            }
        }
        System.out.print(nextLong + " ");
    }





    public static void sixth2Ten(){
        List<Integer> list = new ArrayList<>();
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()){
            String next = scanner.next();
            list.add(Integer.parseInt(next.substring(2),16));
        }
        list.forEach(integer -> System.out.println(integer));
    }







    //连续输入字符串，请按长度为8拆分每个字符串后输出到新的字符串数组；
    //•长度不是8整数倍的字符串请在后面补数字0，空字符串不处理。
    public static void StrSplit(){
        Scanner scanner = new Scanner(System.in);
        StringBuilder stringBuilder = new StringBuilder();
        while (scanner.hasNext()){
            String next = scanner.next();
            stringBuilder.append(next);
            if (stringBuilder.length() % 8 != 0){
                int need = 8 - stringBuilder.length() % 8;
                for (int i = 0; i < need; i++) {
                    stringBuilder.append("0");
                }
            }
        }
        String toString = stringBuilder.toString();
        while (toString.length() !=0){
            System.out.println(toString.substring(0,8));
            toString = toString.substring(8);
        }
    }
}
